// addon.cc
#include <node.h>
#include <node_api.h>
#include "loadcontainer.h"

using namespace v8;
CLoadContainer *pConatainer  = NULL;

namespace app {
  
  using v8::Context;
  using v8::Exception;
  using v8::FunctionCallbackInfo;
  using v8::Isolate;
  using v8::Local;
  using v8::NewStringType;
  using v8::Object;
  using v8::String;
  using v8::Value;
  
  #define WRONG_STRING String::NewFromUtf8(isolate,"Wrong arguments").ToLocalChecked()
  #define PARAM_THROW isolate->ThrowException(Exception::TypeError(WRONG_STRING))
 
	//////////////////////////////////////////////////////////////////////////
    void CreateInstanceFunc(const FunctionCallbackInfo<Value>& args) {

        Isolate* isolate = args.GetIsolate();
        c_assert(isolate != NULL)

        pConatainer = ALLOC_NEW CLoadContainer();
    }

    void DestoryInstanceFunc(const FunctionCallbackInfo<Value>& args) {

        c_assert(pConatainer != NULL)
        delete pConatainer;
    }

    void StartInstanceFunc(const FunctionCallbackInfo<Value>& args) {

        c_assert(pConatainer != NULL)
        logi("pConatainer==>%s","ok");

        Isolate* isolate = args.GetIsolate();
        c_assert(isolate != NULL)

        if (args.Length() < 2) {
            PARAM_THROW;
            logi("args==>%s","error");
            return;
        }

        if (!args[0]->IsString() || !args[1]->IsString()) {
            PARAM_THROW;
            logi("args_type==>%s","error");
            return;
        }


    //////////////////////////////////////////////////////////////////////////
        Local<Context> context = Context::New(isolate);
        v8::String::Utf8Value str_args_1(isolate, 
            args[0]->ToString(context).ToLocalChecked());
        v8::String::Utf8Value str_args_2(isolate,
            args[1]->ToString(context).ToLocalChecked());
    //////////////////////////////////////////////////////////////////////////

        logi("std_com==>%s",*str_args_1);
        logi("license_code==>%s",*str_args_2);
        pConatainer->Init(NULL,*str_args_1,*str_args_2);
        pConatainer->Start(NULL,0);
    }

    void StopInstanceFunc(const FunctionCallbackInfo<Value>& args) {

        c_assert(pConatainer != NULL)
        pConatainer->Stop(NULL,0,0);
        pConatainer->UnInit(NULL);
    
    }
    //////////////////////////////////////////////////////////////////////////
    void PostMessageFunc(const FunctionCallbackInfo<Value>& args) {

    }

    void SendMessageFunc(const FunctionCallbackInfo<Value>& args) {

    }

    void RecvMessageFunc(const FunctionCallbackInfo<Value>& args) {

    }

    void NotifyMessageFunc(const FunctionCallbackInfo<Value>& args) {

    }
    //////////////////////////////////////////////////////////////////////////
    void CreateObject(const FunctionCallbackInfo<Value>& args) {

        Isolate* isolate = args.GetIsolate();
        Local<Context> context = isolate->GetCurrentContext();

        Local<Object> obj = Object::New(isolate);
        obj->Set(context,
                String::NewFromUtf8(isolate,
                                    "msg",
                                    NewStringType::kNormal).ToLocalChecked(),
                                    args[0]->ToString(context).ToLocalChecked()).FromJust();
        args.GetReturnValue().Set(obj);
    }
    //////////////////////////////////////////////////////////////////////////
    void Initialize(Local<Object> exports, Local<Value> module, void* priv) {
    
        //NODE_SET_METHOD(module, "exports", CreateObject);
        //////////////////////////////////////////////////////////////////////////
        NODE_SET_METHOD(exports, "create", CreateInstanceFunc);
        NODE_SET_METHOD(exports, "destory", DestoryInstanceFunc);
        NODE_SET_METHOD(exports, "start", StartInstanceFunc);
        NODE_SET_METHOD(exports, "stop", StopInstanceFunc);
        //////////////////////////////////////////////////////////////////////////
        NODE_SET_METHOD(exports, "postmessage", PostMessageFunc);
        NODE_SET_METHOD(exports, "sendmessage", SendMessageFunc);
        NODE_SET_METHOD(exports, "recvmessage", RecvMessageFunc);
        NODE_SET_METHOD(exports, "notifymessage", NotifyMessageFunc);

    }

    NODE_MODULE(NODE_GYP_MODULE_NAME, Initialize);
}
